//
// Created by hps on 24-4-10.
//

#ifndef CPPCODEHIGHLIGHT_H
#define CPPCODEHIGHLIGHT_H

#include <QtGui/QSyntaxHighlighter>
#include "HeadFiles.h"

namespace hps {

class CPPCodeHighlighter: public QSyntaxHighlighter {
public:
    explicit CPPCodeHighlighter(QTextDocument *parent = nullptr)
        : QSyntaxHighlighter(parent) {
        setHghtLight(parent);
    }

    void addFormat(QString pattern,
                   Qt::GlobalColor color,
                   bool isBold = false,
                   bool isItailc = false,
                   std::string font = "Ubuntu") {
        QTextCharFormat format;
        if (isBold) {
            format.setFontWeight(QFont::Bold);
        }
        format.setFontItalic(isItailc);
        format.setFontFamily(QString(font.c_str()));
        format.setForeground(color);
        QRegularExpression expression;
        expression.setPattern(pattern);
        m_highlightingRules.append({expression, format});
    }

    void setHghtLight(QTextDocument *textDocument = nullptr) {
        addFormat(QString("#include"), Qt::blue);
        addFormat(QString("\\b<.*>"), Qt::darkRed);
        addFormat(QString("\".*\""), Qt::darkRed);
        addFormat(QString("//[^\n]*"), Qt::darkGreen);
        // 关键字
        std::vector<QString> list = {"class", "public", "private", "protected", "override", "struct",
                                     "void", "int", "double", "float", "enum", "union", "bool", "const", "static", "typedef",
                                     "if", "else", "else\\sif", "switch", "case", "break", "for", "continue", "return",
                                     "while", "using", "namespace", "string"};

        for (auto& str : list) {
            addFormat(QString("\\b" + str + "\\b"), Qt::blue);
        }


        m_multiLineCommentFormat.setForeground(Qt::darkGreen);
        m_commentStartExpression = QRegularExpression("/\\*");
        m_commentEndExpression = QRegularExpression("\\*/");
    }
protected:
    void highlightBlock(const QString &text) override {
        for (const HighlightingRule &rule: m_highlightingRules) {
            QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
            while (matchIterator.hasNext()) {
                QRegularExpressionMatch match = matchIterator.next();
                setFormat(match.capturedStart(), match.capturedLength(), rule.format);
            }
        }

        setCurrentBlockState(0);

        int startIndex = 0;
        if (previousBlockState() != 1)
            startIndex = text.indexOf(m_commentStartExpression);

        while (startIndex >= 0) {
            QRegularExpressionMatch match = m_commentEndExpression.match(text, startIndex);
            int endIndex = match.capturedStart();
            int commentLength = endIndex - startIndex + match.capturedLength();
            setFormat(startIndex, commentLength, m_multiLineCommentFormat);
            startIndex = text.indexOf(m_commentStartExpression, startIndex + commentLength);
        }
    }

private:
    typedef struct _HighlightingRule {
        QRegularExpression pattern;
        QTextCharFormat format;
    } HighlightingRule;

    HighlightingRule m_rule;

    QVector<HighlightingRule> m_highlightingRules;
    QTextCharFormat m_multiLineCommentFormat;
    QRegularExpression m_commentStartExpression;
    QRegularExpression m_commentEndExpression;
};

}


#endif //CPPCODEHIGHLIGHT_H
